package uam

import (
	"context"
	"github.com/chromedp/cdproto/network"
	"github.com/chromedp/cdproto/target"
	"github.com/chromedp/chromedp"
	"github.com/sirupsen/logrus"
	"time"
)

type UAMStruct struct {
	url      string
	username string
	pwd      string
	isLogin  bool
	ctx      context.Context
	cancel   context.CancelFunc
}

func NewUAM(boo bool) *UAMStruct {
	s := &UAMStruct{
		url:      "http://192.168.51.212:60000",
		username: "hcy",
		pwd:      "123456Ab",
	}
	s.NewContext(boo)
	//ch := addNewTabListener(s.ctx)
	//s.ctx, s.cancel = chromedp.NewContext(s.ctx, chromedp.WithTargetID(<-ch))
	return s
}

func (s *UAMStruct) NewContext(boo bool) {
	options := []chromedp.ExecAllocatorOption{
		chromedp.Flag("headless", boo), // 是否打开浏览器调试
		chromedp.UserAgent("Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"), // 设置User-Agent
	}
	options = append(chromedp.DefaultExecAllocatorOptions[:], options...)
	// chromdp依赖context上限传递参数
	s.ctx, s.cancel = chromedp.NewExecAllocator(
		context.Background(),
		options...,
	)
	s.ctx, s.cancel = chromedp.NewContext(
		s.ctx,
	)
}

func (s *UAMStruct) Start() error {
	err := chromedp.Run(s.ctx,
		// 监听网络
		chromedp.ActionFunc(func(ctx context.Context) error {
			chromedp.ListenTarget(s.ctx, func(ev interface{}) {
				switch e := ev.(type) {
				case *network.EventResponseReceived:
					go func() {
						switch e.Type {
						case network.ResourceTypeDocument:
							s.docCheckEntrance(e)
						case network.ResourceTypeXHR:
							s.ajaxCheckEntrance(e)
						case network.ResourceTypeWebSocket:
							logrus.Debug("websocket：", e.Response.URL)
						case network.ResourceTypeFetch:
							logrus.Debug("请求 fetch 接口：", e.Response.URL)
						default:
							//	logrus.Debug("暂时用不到的其他类型请求：", e.RequestID.String())
						}
					}()
				}
			})
			return nil
		}),
		// 打开画面
		chromedp.Navigate(s.url),
		chromedp.ActionFunc(func(ctx context.Context) error {
			go func() {
				// 等待新页面打开
				ch := chromedp.WaitNewTarget(s.ctx, func(info *target.Info) bool {
					logrus.Debugf("打开新页面,url: %s,TargetID:%s", info.URL, info.TargetID)
					return info.URL != ""
				})
				// 将新开页面设置到上下文中
				s.ctx, s.cancel = chromedp.NewContext(s.ctx, chromedp.WithTargetID(<-ch))
				// 重新注册一次对网络的监听，否则新纳入监听的页面网络行为无法监听到
				chromedp.Sleep(1 * time.Second)
				// 进入管理端
				logrus.Error("进入管理端 run:")
			}()
			//s.adminLogin(e)
			return nil
		}),
		// 输入账号密码
		chromedp.ActionFunc(func(ctx context.Context) error {
			err := chromedp.Run(s.ctx,
				// 等待登录页面加载完毕
				chromedp.WaitVisible(`#app`, chromedp.ByID),
				// 1. 输入账号密码, SendKeys() 也可以 输入值，但是通常是用来模拟键盘事件来配合页面测试，例如enter按下时页面执行某些操作
				chromedp.SetValue(`document.getElementsByClassName("appearance-none block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-antd-blue-5 focus:border-antd-blue-5 sm:text-sm")[0]`, s.username,
					chromedp.ByJSPath),
				chromedp.SetValue(`document.getElementsByClassName("appearance-none block pl-10 pr-10 w-full py-3 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-antd-blue-5 focus:border-antd-blue-5 sm:text-sm")[0]`, s.pwd,
					chromedp.ByJSPath),
				// 等待两秒
				chromedp.Sleep(1*time.Second),
				// 点击登录按钮
				chromedp.Click(`document.getElementsByClassName("w-full flex justify-center py-2 px-4 border border-transparent rounded shadow text-sm tracking-widest font-medium text-white bg-antd-blue-6 hover:bg-antd-blue-7 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-antd-blue-5")[0]`,
					chromedp.ByJSPath),
			)
			return err
		}),
		// 进入管理页
		chromedp.SetValue(`document.getElementsByClassName("ant-input")[0]`, s.pwd, chromedp.ByJSPath),
		chromedp.Sleep(time.Second*1),
		chromedp.Click(`document.getElementsByClassName("ant-btn ant-btn-primary ant-btn-block btn")[0]`, chromedp.ByJSPath),
		chromedp.ActionFunc(func(ctx context.Context) error {
			logrus.Debug("LoginManagementPage")
			return nil
		}),
	)
	if err != nil {
		logrus.Error(err)
	}
	// 监听程序退出，当页面被关闭时程序自动退出
	err = chromedp.Run(s.ctx,
		s.ListenQuit())
	return err
}

func (s *UAMStruct) ListenNetwork() chromedp.ActionFunc {
	return func(ctx context.Context) error {
		logrus.Debug(" 注册网络监听 ")
		s.ctx = ctx
		_ = network.Enable().Do(s.ctx)
		chromedp.ListenTarget(ctx, func(ev interface{}) {
			switch e := ev.(type) {
			case *network.EventResponseReceived:
				go func() {
					switch e.Type {
					case network.ResourceTypeDocument:
						s.docCheckEntrance(e)
					case network.ResourceTypeXHR:
						s.ajaxCheckEntrance(e)
					case network.ResourceTypeWebSocket:
						logrus.Debug("websocket：", e.Response.URL)
					case network.ResourceTypeFetch:
						logrus.Debug("请求 fetch 接口：", e.Response.URL)
					default:
						//	logrus.Debug("暂时用不到的其他类型请求：", e.RequestID.String())
					}
				}()
			}

		})
		return nil
	}
}

func (s *UAMStruct) ListenQuit() chromedp.ActionFunc {
	return func(ctx context.Context) error {
		for {
			select {
			case <-s.ctx.Done():
				logrus.Info("浏览器被关闭，退出进程")
				return nil
			default:
			}
		}
		return nil
	}
}

func (s *UAMStruct) InputAccountInfo() chromedp.ActionFunc {
	return func(ctx context.Context) error {
		err := chromedp.Run(s.ctx,
			// 等待登录页面加载完毕
			chromedp.WaitVisible(`#app`, chromedp.ByID),
			// 1. 输入账号密码, SendKeys() 也可以 输入值，但是通常是用来模拟键盘事件来配合页面测试，例如enter按下时页面执行某些操作
			chromedp.SetValue(`document.getElementsByClassName("appearance-none block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-antd-blue-5 focus:border-antd-blue-5 sm:text-sm")[0]`, s.username,
				chromedp.ByJSPath),
			chromedp.SetValue(`document.getElementsByClassName("appearance-none block pl-10 pr-10 w-full py-3 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-antd-blue-5 focus:border-antd-blue-5 sm:text-sm")[0]`, s.pwd,
				chromedp.ByJSPath),
			// 等待两秒
			chromedp.Sleep(1*time.Second),
			// 点击登录按钮
			chromedp.Click(`document.getElementsByClassName("w-full flex justify-center py-2 px-4 border border-transparent rounded shadow text-sm tracking-widest font-medium text-white bg-antd-blue-6 hover:bg-antd-blue-7 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-antd-blue-5")[0]`,
				chromedp.ByJSPath),
		)
		return err
	}
}
